# blame: christopher taylor (christopher(dot)paul(dot)taylor(at)gmail(dot)com
# released under terms of MPL (Mozilla Public License) 1.1 http://www.mozilla.org/MPL/
#
import os
import math
import eyeD3

from util import *

from pylevenshtein import pylevenshtein_distance as levenshtein_distance

class SongVecLoader:
	MP3 = "mp3"
	
	@staticmethod
	def load(dir):
		loaded = list()
		loaded_tups = list()
		
		for root, dirs, files in os.walk(dir):
			for f in files:
				fs = f.split(".")
				if len(fs) > 1 and fs[1] == SongVecLoader.MP3:
					songvec = SongVec(root + "\\" + f)
					if songvec.file_name == None:
						continue
					else:
						loaded.append( songvec )
						loaded_tups.append( songvec.toTuple())
					
		return loaded, loaded_tups
		
class SongVec:
	@staticmethod
	def ascii(x): 
		return type(x) != unicode and unicode(x, errors="ignore").encode("ascii", "ignore") or x.encode("ascii", "ignore")
		
	def __init__(self, file_name, orig=None):
		self.file_name = None
		self.artist = None
		self.album = None
		self.song_title = None
		self.cd_id = None
		
		if eyeD3.isMp3File(file_name):
			try:
				audioFile = eyeD3.Mp3AudioFile(file_name)
				tag = audioFile.getTag()
			except:
				print "error processing:\t%s" % ( file_name, )
				return
		else:
			tag = eyeD3.Tag()
			tf = eyeD3.TagFile()
			tag.link(file_name)
		
		self.file_name = file_name
		self.artist = tag.getArtist()
		self.album = tag.getAlbum()
		self.song_title = tag.getTitle()
		#self.cd_id = tag.getCDID()
		
		try :
			self.genre = tag.getGenre() != None and tag.getGenre().getName() or ""
		except:
			self.genre = ""
		
		self.song_vec = ( levenshtein_distance( SongVec.ascii(file_name), SongVec.ascii(self.file_name) ), \
									levenshtein_distance(SongVec.ascii(self.artist), SongVec.ascii(self.artist)), \
									levenshtein_distance(SongVec.ascii(self.album), SongVec.ascii(self.album)), \
									levenshtein_distance(SongVec.ascii(self.song_title), SongVec.ascii(self.song_title)), \
									#levenshtein_distance(ascii(self.cd_id), ascii(self.cd_id)), \
									levenshtein_distance(SongVec.ascii(self.genre), SongVec.ascii(self.genre)) )
		
	def toTuple(self):
		return (self.file_name, self.artist, self.album, self.song_title, self.genre)
		
	def edit_distance(self, song_vec):
		return ( levenshtein_distance(SongVec.ascii(self.file_name), SongVec.ascii(song_vec.file_name)), \
									levenshtein_distance(SongVec.ascii(self.artist), SongVec.ascii(song_vec.artist)), \
									levenshtein_distance(SongVec.ascii(self.album), SongVec.ascii(song_vec.album)), \
									levenshtein_distance(SongVec.ascii(self.song_title), SongVec.ascii(song_vec.song_title)), \
									#levenshtein_distance(ascii(self.cd_id), ascii(song_vec.cd_id)), \
									levenshtein_distance(SongVec.ascii(self.genre), SongVec.ascii(song_vec.genre)) )
									
	def compare(self, song_vec):
		return 0 < self.euclidean_distance(song_vec)
	
	@staticmethod
	def dot(s_vec, song_vec):
		return s_vec[0] * song_vec[0] + \
					s_vec[1] * song_vec[1] + \
					s_vec[2] * song_vec[2] + \
					s_vec[3] * song_vec[3] + \
					s_vec[4] * song_vec[4] #+ \
					#s_vec[5] * song_vec[5]
		
	@staticmethod
	def vec_length(song_vec):
		return math.sqrt( SongVec.dot(song_vec, song_vec) )
